package development.listener;

import java.util.Vector;

import state.GameControl;
import state.GameForm;
import state.ResourceRms;
import state.component.Event;
import state.component.EventListener;
import state.socket.DataPackage;
import state.socket.MapDataPackage;
import state.util.Hashtable;
import state.util.array.ByteArray;
import state.util.array.StringArray;
import development.FrmDownloadResource;
import development.FrmListRoom;
import development.Global;
import development.socket.ProtocolConstants;
import development.socket.SocketClientUtil;

public class DownloadResourceListener extends Listener {
  public static final String DOWN_LOAD_RESOURCE_DONE_ACTION = "downloadResourceDone";
  
  private int totalResource = 0;
  private Hashtable numberOfResourcePerCategory = new Hashtable();
  private int donloadedResource;
  
  public GameForm nextForm;
  private EventListener onDownloadDoneListener;
  private StringArray categoryProfile;
  
  public DownloadResourceListener(String profile) {
    this((StringArray) Global.resourceConfig.get(profile));
  }
  
  public DownloadResourceListener(StringArray categoryProfile1) {
    super(DownloadResourceListener.class.toString());
    this.categoryProfile = categoryProfile1;
    
    // If don't need to download resource then finish
    if (categoryProfile1.len() == 0) {
      new GameControl() {
        public void perform() {
          finishDownloadResource();
        }
      }.setTimeInterval(1000).start();
      return;
    }
    
    for (int i = 0; i < categoryProfile1.len(); i++) {
      SocketClientUtil.requestNumberOfResource(categoryProfile1.get(i));
    }
  }
  
  public void setOnDownloadDoneListener(EventListener onDownloadDoneListener1) {
    this.onDownloadDoneListener = onDownloadDoneListener1;
  }
  
  public void onReceiveResource(DataPackage dataPackage) {
    MapDataPackage resourcePackage = MapDataPackage.getMapPackage(dataPackage);
    String category = resourcePackage.popString("category");
    Hashtable resourceByCategory = (Hashtable) Global.resourceCategory.get(category);
    if (resourceByCategory == null) {
      resourceByCategory = new Hashtable();
      Global.resourceCategory.put(category, resourceByCategory);
    }
    
    Vector imageNames = resourcePackage.getNames();
    for (int i = 0; i < imageNames.size(); i++) {
      String fileName = String.valueOf(imageNames.elementAt(i));
      ByteArray data = resourcePackage.getByteArray(fileName);
      resourceByCategory.put(fileName, new Integer(ResourceRms.saveImageData(category, data)));
      donloadedResource++;
      ((FrmDownloadResource) FrmDownloadResource.instance()).message = "Đang tải dữ liệu...";
      ((FrmDownloadResource) FrmDownloadResource.instance()).message1 = "Đang tải " + donloadedResource + " / " + totalResource;
    }
  }
  
  public void onDownloadResourceDone(DataPackage dataPackage) {
    String category = dataPackage.nextString();
    Hashtable resourceByCategory = (Hashtable) Global.resourceCategory.get(category);
    if (resourceByCategory == null) {
      resourceByCategory = new Hashtable();
      Global.resourceCategory.put(category, resourceByCategory);
    }
    ResourceRms.saveMasterRecord(category, resourceByCategory);
    
    if (isResourceDownloadDone()) {
      finishDownloadResource();
    }
  }
  
  public void onReceiveNumberTotalOfResource(DataPackage dataPackage) {
    String category = dataPackage.nextString();
    int numberOfResource = dataPackage.nextInt();
    numberOfResourcePerCategory.put(category, new Integer(numberOfResource));
    
    // Check if resource is download enough, if not then request download resource
    Hashtable resourceByCategory = (Hashtable) Global.resourceCategory.get(category);
    if (resourceByCategory == null) {
      resourceByCategory = ResourceRms.loadMasterRecord(category);
    }
    
    if ((resourceByCategory == null) || (resourceByCategory.size() < numberOfResource)) {
      SocketClientUtil.requestResource(category);
      totalResource += numberOfResource;
    } else {
      if (isResourceDownloadDone()) {
        finishDownloadResource();
      }
    }
  }
  
  private void finishDownloadResource() {
    ((FrmDownloadResource) FrmDownloadResource.instance()).message = "Tải dữ liệu kết thúc";
    ((FrmDownloadResource) FrmDownloadResource.instance()).message1 = "";
    
    if (onDownloadDoneListener != null) {
      onDownloadDoneListener.onActionPerform(new Event(this, DOWN_LOAD_RESOURCE_DONE_ACTION));
    }
    
    if (nextForm != null) {
      Global.nextState(nextForm, null);
    } else {
      Global.nextState(FrmListRoom.instance(), null);
    }
    Global.authenticateHandle.removeListener(this);
  }
  
  private boolean isResourceDownloadDone() {
    if (donloadedResource >= totalResource) {
      return true;
    }
    
    for (int i = 0; i < categoryProfile.len(); i++) {
      Hashtable resourceByCategory = (Hashtable) Global.resourceCategory.get(categoryProfile.get(i));
      if (resourceByCategory == null) {
        resourceByCategory = ResourceRms.loadMasterRecord(categoryProfile.get(i));
      }
      if (resourceByCategory == null) {
        return false;
      }
      Integer numberOfResourceByCategory = (Integer) numberOfResourcePerCategory.get(categoryProfile.get(i));
      if ((numberOfResourceByCategory == null) || (resourceByCategory.size() < numberOfResourceByCategory.intValue())) {
        return false;
      }
    }
    return true;
  }

  public void onConnectDone() {
  }

  public void onConnectFail() {
  }

  public void onDisconnect() {
  }

  public void onRecieveData(DataPackage dataPackage) {
    int header = dataPackage.getHeader();
    switch (header) {
    case ProtocolConstants.ResponseHeader.NUMBER_OF_TOTAL_RESOURCE_RESPONSE:
      onReceiveNumberTotalOfResource(dataPackage);
      break;
    case ProtocolConstants.ResponseHeader.RESOURCE_RESPONSE:
      onReceiveResource(dataPackage);
      break;
    case ProtocolConstants.ResponseHeader.DOWNLOAD_RESOURCE_DONE_RESPONSE:
      onDownloadResourceDone(dataPackage);
      break;
    }
  }
}
